#pragma once

#include <memory>
#include <functional>
#include <boost/asio/awaitable.hpp>
#include "server/tcp/tcp_server.hpp"
#include "server/http/http_conn.hpp"
#include "base/thread/thread_pool.hpp"
#include "protocol/http/http_define.h"
#include "http_server_session.hpp"
#include "router/tire_tree.hpp"

namespace mms{

class HttpRequest;
class HttpResponse;

class HttpServerBase: public TcpServer<HttpConn>, public HttpRequestHandler<HttpConn>{
using HTTP_HANDLER = std::function<boost::asio::awaitable<void>
            (std::shared_ptr<HttpServerSession<HttpConn>> session,
            std::shared_ptr<HttpRequest> req,
            std::shared_ptr<HttpResponse> resp)>;

public:
    HttpServerBase(ThreadWorker* w):TcpServer(w){}

    virtual ~HttpServerBase();

    bool start(uint16_t port = 80, std::string addr="");
    void stop();

protected:
    bool on_get(const std::string& path, const HTTP_HANDLER& handler);
    bool on_post(const std::string& path, const HTTP_HANDLER& handler);

    virtual bool register_route();
    // TcpSOcketHandler 
    void on_tcp_socket_open(std::shared_ptr<TcpSocket> sock) override;
    void on_tcp_socket_close(std::shared_ptr<TcpSocket> sock) override;

    // HttpHandler
    virtual boost::asio::awaitable<bool> on_new_request(
        std::shared_ptr<HttpServerSession<HttpConn>> session,
        std::shared_ptr<HttpRequest> req,
        std::shared_ptr<HttpResponse> resp
    ) override;

protected:
    TireTree<HTTP_HANDLER> get_route_tree_;
    TireTree<HTTP_HANDLER> post_route_tree_;
};

}// namespace mms